/*
 * 通过模拟在校内网浏览器向219.223.254.55:80发送的登录与维持命令解决非IE浏览器上网的需要
 */

package lang;

import gagazhn.console.Console;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.InputStream;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Date;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {
	public static String sessionID = "-2032226861702157798";
	public static String USER_NAME = "";
	public static String PASSWORD = "";
	public static String IP = "";
	public static String START_TIME = "";
	public static long SYSTEM_TIME = 0;
	
	/*
	 * returnValue:
	 * :0 login success
	 * :1 tick
	 * :2 already login in
	 * :3 user incorrect
	 * :4 password incorrect
	 * :5 unknown error
	 * :6 logout success
	 * :7 the online number reaches the upper-limit
	 * :8 link error
	 */
	public static final int LOGIN_SUCS = 0; 
	public static final int TICK = 1; 
	public static final int ALREADY_LOIN = 2; 
	public static final int USER_INCOR = 3; 
	public static final int PASWD_INCOR = 4; 
	public static final int UNKNOWN_EROR = 5; 
	public static final int LOGOUT_SUCS = 6; 
	public static final int ONLINE_EXC = 7; 
	public static final int LINK_EROR = 8; 
	
	
	private static Console console; 

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// init
		init();
		
		if (args.length == 0) {
			getUserAndPassword();
			
			System.out.println("\n========================================================");
			System.out.println("* 提示: 避免每次登入都要输入用户名和密码的方法.");
			System.out.println("* 1. windows用户: 编辑run.bat文件, 将文件中的%1替换为用户名, 将%2替换为密码.");
			System.out.println("* 2. linux用户: 编辑run.sh文件, 将文件中的$1替换为用户名, 将$2替换为密码.");
			System.out.println("========================================================\n");
			
		} else if (args.length == 2){
			USER_NAME = args[0];
			PASSWORD = args[1];
		} else {
			System.out.println("参数错误!");
			System.out.println("使用方法: run.sh/run.bat [<username> <password>]");
			System.out.println("程序退出.");
			System.exit(0);
		}
		
		try {
			int i = login();
			
			while (true) {
				if (i == Main.LOGIN_SUCS) {
					System.out.println("登入成功!现在可以上网了.\r\n" +
							"需要断网下线时请输入'quit'.\r\n");
					
					break;
				} else {
					if (i == Main.PASWD_INCOR || i == Main.USER_INCOR) {
						System.out.println("登入失败,请检查用户名或密码输入是否正确.");
						getUserAndPassword();
					} else if (i == Main.ALREADY_LOIN) {
						// 当检测到账号已经处于在线状态时:
						// 1.继续tick
						
						keepAlive(false);
						
						System.out.println("续登入成功!现在可以上网了.\r\n" +
							"需要断网下线时请输入'quit'.\r\n");
						
						break;
					} else if (i == Main.ONLINE_EXC) {
						System.out.println("登入失败,同时在线的账号超过最大值,请尝试在大学城自助服务系统中进行下线!");
						
						exitSystem();
					} else {
						System.out.println("Sorry, 遇到了未知错误!");
						
						exitSystem();
					}
				}
				
				// LOGIN
				i = login();
			}
			
			// keepalive
			while (true) {
				Thread.sleep(1000 * 230);
				
				keepAlive(true);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private static void getUserAndPassword() {
		System.out.println("输入用户名(username):");
		USER_NAME = console.getInput()[0];
		
		System.out.println("输入密码(password):");
		PASSWORD = console.getInput()[0];
	}
	
	public static void init() {
		// console
		console = Console.instance();
		LogoutAction c = new LogoutAction();
		GetTimeAction t = new GetTimeAction();
		console.setAction("quit", c);
		console.setAction("logout", c);
		console.setAction("time", t);
		
		console.setHelpInfo("" +
				"可用命令\r\n" +
				"help/?:\t\t获得当前帮助.\r\n" +
				"quit:\t\t注销并退出.\r\n" +
				"time:\t\t获得本次已上线时间.\r\n" +
				"\r\n" +
				"http://code.google.com/p/utsz-http-login-agent/\r\n" +
				"mail: gaga.zhn[AT]gmail.com\r\n\r\n");
		console.run();
		
		// get local ip
		try {
			Socket socket = new Socket("219.223.254.55", 80);
			
			BufferedOutputStream bout = new BufferedOutputStream(socket.getOutputStream());
			BufferedInputStream bin = new BufferedInputStream(socket.getInputStream());
			
			String get = "GET /portal/login.jsp\n\n";
			
			bout.write(get.getBytes());
			bout.flush();
			
			byte[] buff = new byte[256];
			
			int n = bin.read(buff);
			while (n >= 0) {
				n = bin.read(buff);
			}
			
			IP = socket.getLocalAddress().getHostAddress();
			socket.close();
			
			START_TIME = "" + new Date().getTime();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static int login() {
		int toReturn = Main.UNKNOWN_EROR;
		
		try {
			Socket socket = new Socket("219.223.254.55", 80);
			
			BufferedOutputStream bout = new BufferedOutputStream(socket.getOutputStream());
			BufferedInputStream bin = new BufferedInputStream(socket.getInputStream());
			
			
			String LOGIN_CONTENT = "" +
					"username=" + USER_NAME + "&" +
					"password=" + PASSWORD + "&" +
					"serverType=portal&" +
					"isSavePass=on&" +
					"Submit1=Login&" +
					"Language=English&" +
					"ClientIP=" + IP + "&" +
					"sessionID=" + Main.sessionID + "&" +
					"timeoutvalue=60&" +
					"heartbeat=240&" +
					"fastwebornot=false&" +
					"StartTime=" + new Date().getTime() + "&" +
					"shkOvertime=720&" +
					"strOSName=&" +
					"iAdptIndex=&" +
					"strAdptName=&" +
					"strAdptStdName=&" +
					"strFileEncoding=&" +
					"PhysAddr=&" +
					"bDHCPEnabled=&" +
					"strIPAddrArray=&" +
					"strMaskArray=&" +
					"strMask=&" +
					"iDHCPDelayTime=&" +
					"iDHCPTryTimes=&" +
					"strOldPrivateIP=" + IP + "&" +
					"strOldPublicIP=" + IP + "&" +
					"strPrivateIP=" + IP + "&" +
					"PublicIP=" + IP + "&" +
					"iIPCONFIG=0&" +
					"sHttpPrefix=http%3A%2F%2F219.223.254.55&" +
					"title=CAMS+Portal";
			
			String LOGIN = "" + 
					"POST /portal/login.jsp?Flag=0 HTTP/1.1\r\n" +
					"Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, */*\r\n" +
					"Host: 219.223.254.55\r\n" +
					"User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:7.0.1) Gecko/20100101 Firefox/7.0.1" +
					"Connection: keep-alive\r\n" +
					"Referer: http://219.223.254.55/portal/index_default.jsp?Language=English\r\n" +
					"Cookie: filterFlag=true; hello1=" + USER_NAME + "; hello2=true; hello5=portal; hello3=%CE%C6%CF%CF%CE%CF; JSESSIONID=3FE09815890BE974E173D3BCAFB2F927\r\n" +
					"Content-Type: application/x-www-form-urlencoded\r\n" +
					"Content-Length: " + LOGIN_CONTENT.length() + "\r\n" +
					"\r\n" + LOGIN_CONTENT;
			
			SYSTEM_TIME = new Date().getTime();
			
			System.out.println("开始登入...");
			System.out.println("用户名: " + USER_NAME);
			System.out.println("IP地址: " + IP);
			System.out.println();
			
			// sent login request
			bout.write(LOGIN.getBytes());
			bout.flush();
			
			toReturn = getResponse(bin);
		} catch (Exception e) {
			System.out.println("连接219.223.242.253.55失败,请检查网路.");
			toReturn = Main.LINK_EROR;
		}
		
		return toReturn;
	}
	
	public static void keepAlive(boolean printInfo) {
		String LOGIN_KEEP_ALIVE = "" +
		"GET /portal/loginDown.jsp?Language=Chinese&strPrivateIP=" + IP + "&" +
				"PublicIP=" + IP + "&" +
				"strOldPrivateIP=" + IP + "&" +
				"strOldPublicIP=" + IP + "&" +
				"sessionID=" + Main.sessionID + "&" +
				"StartTime=" + START_TIME + "&" +
				"heartbeat=240&" +
				"shkOvertime=720&" +
				"linkStatues=1&" +
				"username=" + USER_NAME + "&" +
				"strUserPortNo=SR6602-vlan-00-0000@vlan-SSID-@SSID&" +
				"iUserStatus=99&" +
				"iIPCONFIG=0&" +
				"iTimeStamp=1317174759859 HTTP/1.1\r\n" +
		"Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, */*\r\n" +
		"Host: 219.223.254.55\r\n" +
		"User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:7.0.1) Gecko/20100101 Firefox/7.0.1" +
		"Connection: keep-alive\r\n" +
		"Referer: http://219.223.254.55/portal/login.jsp?Flag=0\r\n" +
		"Cookie: filterFlag=true; hello1=" + USER_NAME + "; hello2=true; hello5=portal; hello3=%CE%C6%CF%CF%CE%CF; JSESSIONID=3FE09815890BE974E173D3BCAFB2F927\r\n" +
		"\r\n";
		
		
		
		try {
			Socket socket = new Socket("219.223.254.55", 80);
			
			BufferedOutputStream bout = new BufferedOutputStream(socket.getOutputStream());
			BufferedInputStream bin = new BufferedInputStream(socket.getInputStream());
			
			bout.write(LOGIN_KEEP_ALIVE.getBytes());
			bout.flush();
			
			getResponse(bin);
			
			//tick INFO
//			System.out.println("INFO: sessionID: " + Main.sessionID);
//			System.out.println("INFO: StartTime: " + Main.START_TIME);
//			System.out.println("INFO: IP: " + Main.IP);
//			System.out.println("");
			if (printInfo) {
				GetTimeAction.printTimeInfo();
			}
			
		} catch (Exception e) {
			System.out.println("tick失败,3分钟后重试");
		}
	}
	
	public static int logout() {
		int toReturn = Main.UNKNOWN_EROR;
		
		try {
			Socket socket = new Socket("219.223.254.55", 80);
			
			BufferedOutputStream bout = new BufferedOutputStream(socket.getOutputStream());
			BufferedInputStream bin = new BufferedInputStream(socket.getInputStream());
			
			String LOGOUT_CONTENT = "" +
					"username=" + USER_NAME + "&" +
					"password=" + PASSWORD + "&" +
					"serverType=portal&" +
					"isSavePass=on&" +
					"Language=English&ClientIP=" + IP + "&" +
					"sessionID=" + Main.sessionID + "&" +
					"timeoutvalue=60&" +
					"heartbeat=240&" +
					"fastwebornot=false&" +
					"StartTime=&" +
					"shkOvertime=720&" +
					"strOSName=&" +
					"iAdptIndex=&" +
					"strAdptName=&" +
					"strAdptStdName=&" +
					"strFileEncoding=&" +
					"PhysAddr=&" +
					"bDHCPEnabled=&" +
					"strIPAddrArray=&" +
					"strMaskArray=&" +
					"strMask=&" +
					"iDHCPDelayTime=&" +
					"iDHCPTryTimes=&" +
					"strOldPrivateIP=" + IP + "&" +
					"strOldPublicIP=" + IP + "&" +
					"strPrivateIP=" + IP + "&" +
					"PublicIP=" + IP + "&" +
					"iIPCONFIG=0&" +
					"sHttpPrefix=&" +
					"title=CAMS+Portal";
			
			String LOGOUT = "" + 
					"POST /portal/logout.jsp HTTP/1.1\r\n" +
					"Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, */*\r\n" +
					"Host: 219.223.254.55\r\n" +
					"User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:7.0.1) Gecko/20100101 Firefox/7.0.1" +
					"Connection: keep-alive\r\n" +
					"Referer: http://219.223.254.55/portal/index_default.jsp?Language=English\r\n" +
					"Cookie: filterFlag=true; hello1=" + USER_NAME + "; hello2=true; hello5=portal; hello3=%CE%C6%CF%CF%CE%CF; JSESSIONID=3FE09815890BE974E173D3BCAFB2F927\r\n" +
					"Content-Type: application/x-www-form-urlencoded\r\n" +
					"Content-Length: " + LOGOUT_CONTENT.length() + "\r\n" +
					"\r\n" + LOGOUT_CONTENT;
			
			bout.write(LOGOUT.getBytes());
			bout.flush();
			
			toReturn = getResponse(bin);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return toReturn;
	}
	
	public static void exitSystem() {
		try {
			System.out.println("程序会在3秒后退出.");
			System.out.print("3... ");
			Thread.sleep(1000);
			System.out.print("2... ");
			Thread.sleep(1000);
			System.out.print("1... ");
			Thread.sleep(1000);
			System.out.println("exit.");
			System.exit(0);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private static int getResponse(BufferedInputStream bin) {
		
		int returnValue = 0;
		byte[] buff = new byte[256];
		
		try {
			StringBuilder sb = new StringBuilder();
			
			int n = bin.read(buff);
			while (n >= 0) {
//				System.out.write(buff, 0, n);
				sb.append(new String(buff, 0, n));
				n = bin.read(buff);
			}
			
			// login state
			if (sb.toString().indexOf("Incorrect password") >= 0) {
				returnValue = 4;
			} else if (sb.toString().indexOf("noresize src=/portal/loginTop.jsp") >= 0) {
				returnValue = 0;
			} else if (sb.toString().indexOf("You have logged in!") >= 0) {
				returnValue = 2;
			} else if (sb.toString().indexOf("The user does not exist") >= 0) {
				returnValue = 3;
			} else if (sb.toString().indexOf("You have logged out!") >= 0) {
				returnValue = Main.LOGOUT_SUCS;
			} else if (sb.toString().indexOf("The online number reaches the upper-limit") >= 0) {
				returnValue = Main.ONLINE_EXC;
			} else {
				returnValue = 1;
			}
			
			// sessionID
			Pattern pattern = Pattern.compile("name=sessionID value=(-?\\d+)");
			Matcher matcher = pattern.matcher(sb.toString());
			if (matcher.find()) {
				Main.sessionID = matcher.group(1);
			} 
			
				pattern = Pattern.compile("sessionID=(-?\\d+)");
				matcher = pattern.matcher(sb.toString());
			if (matcher.find()) {
				Main.sessionID = matcher.group(1);
			}
			
			// StartTime
			pattern = Pattern.compile("name=StartTime value=(-?\\d+)");
			matcher = pattern.matcher(sb.toString());
			if (matcher.find()) {
				Main.START_TIME = matcher.group(1);
			} 
			
			pattern = Pattern.compile("StartTime=(-?\\d+)");
			matcher = pattern.matcher(sb.toString());
			if (matcher.find()) {
				Main.START_TIME = matcher.group(1);
			}
			
			bin.close();
		} catch (Exception e) {
//			e.printStackTrace();
			returnValue = Main.LINK_EROR;
		}
		
		return returnValue;
	}
}
